﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NFit.Core.Errors;

namespace NFit.Core.Fixtures
{
    /// <summary>
    /// Base class for Action fixtures
    /// </summary>
    public abstract class ActionFixture : AbstractFixture
    {
        /// <summary>
        /// Fill arguments and definition if necessary
        /// </summary>
        /// <returns></returns>
        public override void Resolve()
        {
            //FixtureDefinition.Rows.RemoveAt(0);
        }

        /// <summary>
        /// Execute the fixture for the provided row
        /// </summary>
        public override bool Run()
        {
            ProcessCheck();
            ProcessReject();
            ProcessEnter();
            ProcessPress();

            if (!Row.Status.Success.HasValue)
            {
                Row.Status.Success = false;
                Row.Status.NestedError = ElementNotFoundError.Keyword(Row[1].Text);
                return false;
            }

            return true;
        }

        /// <summary>
        /// Process a check operation
        /// </summary>
        protected virtual void ProcessCheck()
        {
            if (Context.NameProvider.IsAKeywordFor("check", Row[0].Text))
            {
                Row.Status.Success = true;
                string methodName = Context.NameProvider.ElementName(Row[1].Text);
                Row[1].Status.Success = ReflectionHelper.RunMethod(Context, this, Row[1], Row[2], methodName, true, null);
            }
        }

        /// <summary>
        /// Process a reject operation
        /// </summary>
        protected virtual void ProcessReject()
        {
            if (Context.NameProvider.IsAKeywordFor("reject", Row[0].Text))
            {
                Row.Status.Success = true;
                string methodName = Context.NameProvider.ElementName(Row[1].Text);
                ReflectionHelper.RunMethod(Context, this, Row[1], Row[2], methodName, true, null);
                if (Row[1].Status.NestedError is ValueMismatchError)
                {
                    Row[1].Status.Success = true;
                    Row[1].Status.NestedError = null;
                }
                else
                {
                    Row[1].Status.Success = false;
                    Row[1].Status.NestedError = new ValueMismatchError(Row[2].ExpectedValue, Row[2].ActualValue);
                }
            }
        }

        /// <summary>
        /// Process a enter operation
        /// </summary>
        protected virtual void ProcessEnter()
        {
            if (Context.NameProvider.IsAKeywordFor("enter", Row[0].Text))
            {
                Row.Status.Success = true;
                string methodName = Context.NameProvider.ElementName(Row[1].Text);
                string[] args = Row.GetArray(2);
                Row[1].Status.Success = ReflectionHelper.RunMethod(Context, this, Row[1], Row[1], methodName, false, args);
            }
        }

        /// <summary>
        /// Process a press operation
        /// </summary>
        protected virtual void ProcessPress()
        {
            if (Context.NameProvider.IsAKeywordFor("press", Row[0].Text))
            {
                Row.Status.Success = true;
                string methodName = Context.NameProvider.ElementName(Row[1].Text);
                Row[1].Status.Success = ReflectionHelper.RunMethod(Context, this, Row[1], Row[1], methodName, false, null);
            }
        }    
    }
}
